package PrjGNSS

/*
   可单独使用

   使用步骤:
     1. appendFromConf
     2. GetSrcTable
*/

import (
	"dgo/goutils/gnss"
	"dgo/goutils/utils"
	"errors"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"sort"
	"sync"
)

type CasterMountPointService struct {
	lock     sync.RWMutex
	srcTable string
	srcText  string
	listMap  map[string]*CasterMountPointPojo // mountpoint -> pojo
}

var (
	CasterMPService *CasterMountPointService = &CasterMountPointService{
		listMap: make(map[string]*CasterMountPointPojo),
	}
)

func (this *CasterMountPointService) rebuildSrcTable() {
	this.lock.RLock()
	sortlst := make([]*CasterMountPointPojo, 0, len(this.listMap))
	for _, v := range this.listMap {
		if v.show {
			sortlst = append(sortlst, v)
		}
	}
	this.lock.RUnlock()

	sort.Slice(sortlst, func(i, j int) bool {
		i_itm := sortlst[i]
		j_itm := sortlst[j]
		return i_itm.LessCompareTo(j_itm)
	})

	var sb utils.BytesBuilder
	for _, v := range sortlst {
		sb.WriteString(v.GetSrcText())
	}
	this.srcTable = sb.String()
}

func (this *CasterMountPointService) GetSrcTable() string {
	if len(this.srcTable) == 0 {
		this.rebuildSrcTable()
	}
	return gnss.BuildSourceTableTextWithDate(this.srcTable, "NTRIP VRS")
}

func (this *CasterMountPointService) Exists(mountpoint string) bool {
	this.lock.RLock()
	defer this.lock.RUnlock()
	return this.listMap[mountpoint] != nil
}

func (this *CasterMountPointService) Range(rangefunc func(k string, v *CasterMountPointPojo) bool) {
	this.lock.RLock()
	defer this.lock.RUnlock()
	for k, v := range this.listMap {
		if !rangefunc(k, v) {
			break
		}
	}
}

func (this *CasterMountPointService) Cleanup() {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.listMap = make(map[string]*CasterMountPointPojo)
	this.srcTable = ""
}

// /  ==================  读取配置
func (this *CasterMountPointService) LoadFromFile(filen string) error {
	strName := filen
	filename := utils.GetExecuteFileDirectory()
	filename += utils.PathSeparator + strName
	if !utils.FileIsExists(filename) {
		filename = utils.GetExecuteFileDirectory() + utils.PathSeparator + "config" + utils.PathSeparator + strName
		if !utils.FileIsExists(filename) {
			filename = strName
			if !utils.FileIsExists(filename) {
				filename = "config" + utils.PathSeparator + strName
			}
		}
	}

	if !utils.FileIsExists(filename) {
		return errors.New(fmt.Sprintf("未找到任何的配置文件[%s]", strName))
	}

	utils.Log.Infof("加载配置文件:%s", filename)

	fileConf, err := wrapper.NewSVFromFile(filename)
	if err != nil {
		return errors.New(fmt.Sprintf("加载配置文件[%s]出现异常:%s", filename, err.Error))
	}

	this.AppendFromConf(fileConf)

	return nil
}

func (this *CasterMountPointService) AppendFromConfStr(confstr string) *CasterMountPointService {
	conf, err := wrapper.NewSVFromBuf([]byte(confstr))
	if err != nil {
		utils.Log.Warnf("加载Conf异常:%s", err.Error())
		return this
	}

	this.AppendFromConf(conf)
	return this

}

func (this *CasterMountPointService) AppendFromConf(conf *wrapper.SuperValue) bool {
	if conf == nil {
		return false
	}
	var lstConf *wrapper.SuperValue
	if conf.IsObject() {
		lstConf = conf.AsRecordByName("list")
		if lstConf == nil {
			lstConf = conf.AsRecordByName("sourceTable")
		}
	} else if conf.IsArray() {
		lstConf = conf
	}

	n := 0
	for i := 0; i < lstConf.Length(); i++ {
		if this.AppendFromRec(lstConf.AsRecord(i)) {
			n++
		}
	}
	return n > 0
}

func (this *CasterMountPointService) AppendFromRec(conf *wrapper.SuperValue) bool {
	strid := conf.AsString("mountpoint", "")
	if len(strid) == 0 {
		return false
	}

	innerConf := conf.Find("__data")
	this.lock.Lock()
	defer this.lock.Unlock()
	mp := this.listMap[strid]
	if mp == nil {
		mp = &CasterMountPointPojo{}
		mp.Id = strid
		this.listMap[strid] = mp
	}

	mp.srcText = conf.AsString("showtext", "")
	mp.show = conf.AsBool("show", true)
	mp.srcType = conf.AsInt("srctype", 0)
	if innerConf != nil {
		mp.Conf = innerConf.Clone()
	}
	this.srcTable = ""
	return true
}
